#include "sdio.h"
#include "gpio.h"
#include "../PRINT/my_printf.h"
#include "../VIC/vic_reg.h"
#include "../PUBLIC/test.h"

/*
 * GPIOA29/SDCLK0   GPIOA31/SDCMD0   GPIOB1/SDDAT0[0]
 * GPIOB3/SDDAT0[0] GPIOB5/SDDAT0[3] GPIOB7/SDDAT0[3]
 */

void de(uint t){
    while(t--);
}

void sdio0_init(){
    int timeout;

    SDIO sdio0 = (SDIO)BASE_ADDR_SD0;

    IP_RESET_REGISTER1 |= (1 << 6);
    ALIVEPWRGATEREG |= (1 << 0);
    ALIVEGPIOPADOUTENBSETREG |= (1 << 1);

    printf("ALIVEGPIOPADOUTENBREADREG [%x] %x\r\n", (u32)&ALIVEGPIOPADOUTENBREADREG, ALIVEGPIOPADOUTENBREADREG);

    GPIOAALTFN1 &= ~((3 << 26) | (3 << 30));
    GPIOAALTFN1 |= ((1 << 26) | (1 << 30));
    GPIOBALTFN0 &= ~((3 << 2) | (3 << 6) | (3 << 10) | (3 << 14));
    GPIOBALTFN0 |= ((1 << 2) | (1 << 6) | (1 << 10) | (1 << 14));

    vic_init(43, (u32)sdio0_ISR);

    SDMMCCLKGEN0L &= ~((0xFF << 5) | (0x7 << 2));
    SDMMCCLKGEN0L |= (((200 - 1) << 5) | (2 << 2));    // PLL[2] / 200 = 4MHz
    SDMMCCLKENB |= (1 << 2);            // 时钟生成使能

    // printf("SDMMCCLKGEN0L [%x] %x\r\n", (u32)&SDMMCCLKGEN0L, SDMMCCLKGEN0L);
    // printf("SDMMCCLKENB [%x] %x\r\n", (u32)&SDMMCCLKENB, SDMMCCLKENB);

    sdio0->CLKDIV |= 10;         // 分频
    sdio0->CLK_SOURCE = 0;
    
    sdio0->CTYPE = 0;           // 数据位宽，1-bit
    sdio0->BLKSIZ = 512;        // 块大小
    
    sdio0->CTRL |= (1 << 4);    // 中断使能
    sdio0->CLKENA |= (1 << 0);  // 时钟使能
    sdio0->INTMASK |= ((1 << 16) | (1 << 2)); // mask使能

    printf("POWER_ENABLE %x\r\n", sdio0->POWER_ENABLE);
    sdio0->POWER_ENABLE = 1;    // 上电

    // 发送CMD0
    sdio0->CMDARG = 0;
    sdio0->CMD = ((1 << 31) | (1 << 29) | (1 << 15));

    timeout = 0x10000;
    while(--timeout){
        if(((sdio0->STATUS > 4) & 0xF) == 1 || ((sdio0->RINTSTS >> 2) & 1) == 1){
            printf("OK %x %x\r\n", sdio0->STATUS, sdio0->RINTSTS);
            break;
        }
    }
    
    if(timeout == 0){
        printf("cmd0 timeout %x %x\r\n", sdio0->STATUS, sdio0->CMD);
    }

    // 发送CMD2
    sdio0->CMDARG = 0;
    sdio0->CMD = ((1 << 31) | (1 << 7) | (1 << 6) | (2 << 0));

    timeout = 0x10000;
    while(--timeout){
        if(((sdio0->STATUS > 4) & 0xF) == 1 || sdio0->RINTSTS){
            printf("OK %x %x\r\n", sdio0->STATUS, sdio0->RINTSTS);
            break;
        }
    }

    if(timeout == 0){
        printf("cmd2 timeout %x %x\r\n", sdio0->STATUS, sdio0->CMD);
    }

    printf("clk_source [%x] %x %x %x %x\r\n", (u32)&sdio0->RESP0, sdio0->RESP0, sdio0->RESP1, sdio0->RESP2, sdio0->RESP3);
}

void sdio0_ISR(){
    printf("sdio0_ISR %x\r\n", 0);
}